package io.github.cocoa.module.socket.service.sample;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import io.github.cocoa.framework.common.core.KeyValue;
import io.github.cocoa.framework.common.exception.ServiceException;
import io.github.cocoa.framework.common.pojo.CommonResult;
import io.github.cocoa.framework.common.pojo.PageResult;
import io.github.cocoa.module.socket.controller.admin.sample.vo.*;
import io.github.cocoa.module.socket.convert.sample.SampleInfoConvert;
import io.github.cocoa.module.socket.dal.dataobject.sample.SampleInfoDO;
import io.github.cocoa.module.socket.dal.mysql.sample.SampleInfoMapper;
import io.github.cocoa.module.socket.mq.producer.sample.SampleInfoProducer;
import io.github.cocoa.module.system.api.mail.MailSendApi;
import io.github.cocoa.module.system.api.mail.dto.MailSendSingleToUserReqDTO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

import static io.github.cocoa.framework.common.exception.util.ServiceExceptionUtil.exception;
import static io.github.cocoa.module.socket.enums.sample.SampleInfoErrorCodeConstant.*;

/**
 * 示例信息 Service 实现类
 *
 * @author James
 */
@Service
@Validated
public class SampleInfoServiceImpl implements SampleInfoService {

    @Resource
    private MailSendApi mailSendApi; // feign 远程 rpc 调用
    @Resource
    private SampleInfoProducer sampleInfoProducer; // 示例信息生产者

    @Resource
    private SampleInfoMapper sampleInfoMapper;

    @Override
    public Long createInfo(SampleInfoCreateReqVO createReqVO) {
        validateForCreateOrUpdate(null);
        // 插入
        SampleInfoDO info = SampleInfoConvert.INSTANCE.convert(createReqVO);
        sampleInfoMapper.insert(info);
        // 返回
        return info.getId();
    }

    @Override
    public void updateInfo(SampleInfoUpdateReqVO updateReqVO) {
        validateForCreateOrUpdate(updateReqVO.getId());
        // 更新
        SampleInfoDO updateObj = SampleInfoConvert.INSTANCE.convert(updateReqVO);
        sampleInfoMapper.updateById(updateObj);
    }

    @Override
    public void deleteInfo(Long id) {
        // 校验存在
        validateInfoExists(id);
        // 删除
        sampleInfoMapper.deleteById(id);
    }

    private void validateForCreateOrUpdate(Long id) {
        // 校验自己存在
        validateInfoExists(id);
    }

    private void validateInfoExists(Long id) {
        if (id == null) {
            return;
        }
        if (sampleInfoMapper.selectById(id) == null) {
            throw exception(SAMPLE_INFO_NOT_EXISTS);
        }
    }

    @Override
    public SampleInfoDO getInfo(Long id) {
        return sampleInfoMapper.selectById(id);
    }

    @Override
    public List<SampleInfoDO> getInfoList(Collection<Long> ids) {
        return sampleInfoMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<SampleInfoDO> getInfoPage(SampleInfoPageReqVO pageReqVO) {
        return sampleInfoMapper.selectPage(pageReqVO);
    }

    @Override
    public List<SampleInfoDO> getInfoList(SampleInfoExportReqVO exportReqVO) {
        return sampleInfoMapper.selectList(exportReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public SampleInfoImportRespVO importInfoList(List<SampleInfoImportExcelVO> importInfoList, Boolean isUpdateSupport) {
        if (CollUtil.isEmpty(importInfoList)) {
            throw exception(SAMPLE_INFO_IMPORT_LIST_IS_EMPTY);
        }
        SampleInfoImportRespVO respVO = SampleInfoImportRespVO.builder().createSamples(new ArrayList<>()).updateSamples(new ArrayList<>()).failureSamples(new LinkedHashMap<>()).build();
        importInfoList.forEach(importSampleInfo -> {
            // 校验，判断是否有不符合的原因
            try {
                validateForCreateOrUpdate(null);
            } catch (ServiceException ex) {
                respVO.getFailureSamples().put(importSampleInfo.getId(), ex.getMessage());
                return;
            }
            // 判断如果不存在，在进行插入
            SampleInfoDO existSampleInfo = sampleInfoMapper.selectOne(SampleInfoDO::getId, importSampleInfo.getId());
            if (existSampleInfo == null) {
                sampleInfoMapper.insert(SampleInfoConvert.INSTANCE.convert(importSampleInfo));
                respVO.getCreateSamples().add(importSampleInfo.getId());
                return;
            }
            // 如果存在，判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureSamples().put(importSampleInfo.getId(), SAMPLE_INFO_EXISTS.getMsg());
                return;
            }
            SampleInfoDO updateSampleInfo = SampleInfoConvert.INSTANCE.convert(importSampleInfo);
            updateSampleInfo.setId(existSampleInfo.getId());
            sampleInfoMapper.updateById(updateSampleInfo);
            respVO.getUpdateSamples().add(importSampleInfo.getId());
        });
        return respVO;
    }

    @Override
    public CommonResult<Long> sendSingleMailToAdmin(MailSendSingleToUserReqDTO reqDTO) {
        return mailSendApi.sendSingleMailToAdmin(reqDTO);
    }

    private static List<KeyValue<String, Object>> getKeyValues() {
        List<KeyValue<String, Object>> templateParams = new ArrayList<>();
        templateParams.add(new KeyValue<>("key", "value"));
        return templateParams;
    }

    @Override
    public Long sendSampleInfoMessage() {
        List<KeyValue<String, Object>> templateParams = getKeyValues();
        long randomLong = RandomUtil.randomLong();
        sampleInfoProducer.sampleSendMessage(randomLong, templateParams);
        return randomLong;
    }

    @Override
    public Long oneMethodMessage() {
        List<KeyValue<String, Object>> templateParams = getKeyValues();
        long randomLong = RandomUtil.randomLong();
        sampleInfoProducer.oneMethodMessage(randomLong, templateParams);
        return randomLong;
    }

    @Override
    public Long twoMethodMessage() {
        List<KeyValue<String, Object>> templateParams = getKeyValues();
        long randomLong = RandomUtil.randomLong();
        sampleInfoProducer.twoMethodMessage(randomLong, templateParams);
        return randomLong;
    }

}
